# base working

library(dplyr)
library(tidyverse)
library(readr)
library(ggplot2)
library(dashHtmlComponents)
library(dashCoreComponents)
library(plotly)
library(dash)
library(purrr)

suf_data <- read.csv(file = 'data/processed/sufang_clean_df.csv')
j_data <- read_csv("data/processed/jasmine_df.csv")
New names:
* `` -> ...1
Rows: 3939 Columns: 7
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): title, cast, listed_in, rating
dbl (3): ...1, cast_count, release_year

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
data <- read_csv("data/processed/clean_df.csv")
New names:
* `` -> ...1
Rows: 3939 Columns: 13
── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (10): title, director, cast, country, date_added, rating, duration, listed_in, description, type
dbl  (3): ...1, show_id, release_year

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
j_data <- j_data %>% filter(is.na(j_data$cast_count) == FALSE)

cast_data <- j_data %>% 
  group_by(release_year) %>%
  summarize(mean_cast_count = mean(cast_count))
 p <- cast_data %>%
      ggplot(aes(x=release_year,
                 y=mean_cast_count)) +
      geom_point(fill= "red2", color = "black", shape = 21, size = 3) +
      ggtitle("Average Cast Size Per Year") +
      xlab("Release Year") +
      ylab("Avg. Cast Size") +
      xlim(1942, 2020) +
      theme(plot.title = element_text(hjust = 0.5, color = "white"),
            panel.background = element_blank(),
            panel.grid = element_line(color = "gray90"),
            axis.line = element_line(colour = "black"),
            plot.background = element_rect(fill = '#171614', colour = '#171614'),
            axis.text = element_text(color="white"),
            axis.title.x = element_text(color="white"),
            axis.title.y = element_text(color="white")
      )
    ggplotly(p + aes(text = release_year), tooltip = 'release_year')  %>% layout(plot_bgcolor = '000000')
c("#CE2626", 
  "#820263", 
  "#FBBA72", 
  "#EFAAC4", 
  "#A56124", 
  "#D30C7B",
  "#520F2A", 
  "#FF3C38", 
  "#FF8C42", 
  "#F991CC", 
  "#A05BFA", 
  "#9F2042")
summarize(mean_cast_count = mean(cast_count))

app <- Dash$new(external_stylesheets = dbcThemes$BOOTSTRAP)


app$layout(
  dbcContainer(
    list(
    
    # title card 
    dbcRow(
      list(
        dbcCard(
          dbcCardBody(
            list(h4("Netflix Movie Dashboard: Visualize movie trends on the world's most popular streaming platform!", className = "card-title")),
            dbcCol(
            style=list("font-weight"="bold", "font-size"="85%"),
            ), # dbcCol
          ), # dbcCardBody
          color ="dark", 
          inverse=TRUE
        ) #dbcCard
    ), # list
    ), # dbcRow
    
    # first row
     dbcRow(
      list(
      
       # Jasmine's plot
         dbcCol( 
          dbcCard(
            dbcCardBody(
              div(
                 list(
                  dccGraph(id='scatter'),
                  htmlLabel('Year Range'),
                  
                  dccSlider(
                    id='xslider',
                    min=1942,
                    max=2019,
                    marks = list(
                      '1942' = '1942',
                      '1962' = '1962',
                      '1982' = '1982',
                      '2002' = '2002',
                      '2019'= '2019'
                      ),
                  value=2002)
              )
              
            ) # html
          ), # dbcCardBody
        color="dark"
        ), # dbcCard
        md=6,
      ), # Jasmine dbcCol
      
      # Mahsa plot
      
      dbcCol(
          dbcCard(
            dbcCardBody(
              div(
                list(
                  dccGraph(id='plot_line'),

                  dccDropdown(
                    id='rating-select',
                    options = data$rating %>%
                      purrr::map(function(rating,pop) list(label = rating, value = rating)),
                    value=list("TV-G","TV-MA", "TV-14","TV-Y7"),
                    multi=TRUE
                    ),

                  dccRangeSlider(
                    id='my-range-slider',
                    min=1942,
                    max=2020,
                    marks =
                      list(
                        '1942' = '1942',
                        '1960' = '1960',
                        '1980' = '1980',
                        '2000' = '2000',
                        '2020' = '2020'
                      ),
                    value=list(2003, 2020)
                  )
                ) # list
              ) # div
            ), # dbcCardBody
            color="dark"
          ), # dbcCard
    md=6), # close dbcCol
      
    dbcRow(
      dbcCol(
        dbcCard(
         dbcCardBody(
              div(
                
                ##
                
      list(
      dccGraph(id='plot-area'),
      htmlLabel("Year"),
      dccRangeSlider(id='year3',
                min = min(suf_data$release_year),
                max= max(suf_data$release_year),
                value=list(1995, 2020),
                marks=list(
                  '1970'= "1970",
                  '1975'= "1975",
                  '1980'= "1980",
                  '1985'= "1985",
                  '1990'= "1990",
                  '1995'= "1995",
                  '2000'= "2000",
                  '2005'= "2005",
                  '2010'= "2010",
                  '2015'= "2015",
                  '2020'= "2020"
                )
                ),
      htmlLabel("Duration"),
      dccRangeSlider(id='duration3',
                min = min(suf_data$duration),
                max = max(suf_data$duration),
                value=list(60, 120),
                marks=list(
                  '10'=  "10 min",
                  '30'= "30 min",
                  '50'= "50 min",
                  '70'= "70 min",
                  '90'= "90 min",
                  '110'= "110 min",
                  '130'= "130 min",
                  '150'= "150 min",
                  '170'= "170 min",
                  '190'= "190 min",
                  '210'= "210 min",
                  '230'= "230 min")
          )
        )
                
                ###
              ) # div
         ), # dbcCardBody
      color="dark"
        ) # dbcCard
      )
    )

      ) # close list
    ) # first row
    ), # close list
    style=list(backgroundColor = "#000000")
  ) # container  
) 

# jasmine callback 
app$callback(
  output('scatter', 'figure'),
  list(input('xslider', 'value')),
  function(xcol) {

    p <- cast_data %>%
      ggplot(aes(x=release_year,
                 y=mean_cast_count)) +
      geom_point(fill= "red2", color = "black", shape = 21, size = 3) +
      ggtitle("Average Cast Size Per Year") +
      xlab("Release Year") +
      ylab("Avg. Cast Size") +
      xlim(1942, xcol) +
      theme(plot.title = element_text(hjust = 0.5),
            panel.background = element_blank(),
            panel.grid = element_line(color = "gray90"),
            axis.line = element_line(colour = "black"),
            plot.background = element_rect(fill = '#171614', colour = '#171614')
            
      )
    ggplotly(p + aes(text = release_year), tooltip = 'release_year')  %>% layout(plot_bgcolor = '000000')
  }
)

# mahsa

app$callback(
  output('plot_line', 'figure'),
  list(input('rating-select', 'value'),
       input('my-range-slider','value')),
  function(ratings_range,year_range) {
    df <- na.omit(data) %>% 
      filter(release_year > year_range[1],release_year < year_range[2]) %>%
      filter(rating %in% ratings_range) %>%
      group_by(release_year,rating) %>% 
      summarise(count = length(rating))
    
    plot  <- ggplot(df ,aes(x = release_year, y = count, color = rating)) +
      geom_line()+      
      scale_size(range = c(2, 12)) +
      ggtitle('Movie rating in Netflix in different years') +
      labs(x = 'Years', y= "Number of movie") +
      theme_bw() +
      theme(text =  element_text(size = 10)) +
      ggthemes::scale_color_tableau() 
    
    ggplotly(plot)
  }
)

# sufang callback

app$callback(
  output('plot-area', 'figure'),
  list(input('year3', 'value'),
       input('duration3', 'value')),
  function(year_range,duration_range){
    data_filt <- suf_data %>%
      dplyr::filter((release_year > year_range[1] & release_year < year_range[2]) & (duration > duration_range[1] & duration < duration_range[2]))
    p1 <- ggplot(data_filt, aes(x = forcats::fct_infreq(country)),text = name) +
      geom_bar(stat = 'count', color = "black", fill = "red2") +
      ggtitle('Which Countries Make the Most Movies?') +
      labs(x = 'Country') +
      labs(y = 'Number of Movies Produced')+
      theme_classic() +
      ggthemes::scale_color_tableau()+
      theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
    ggplotly(p1)
  }
)


# app$run_server(host = '0.0.0.0')
app$run_server(debug = T) # use when running locally

# work on 
library(dash)
library(dashCoreComponents)

Attaching package: ‘dashCoreComponents’

The following objects are masked from ‘package:dash’:

    dccChecklist, dccConfirmDialog, dccConfirmDialogProvider, dccDatePickerRange, dccDatePickerSingle,
    dccDropdown, dccGraph, dccInput, dccInterval, dccLink, dccLoading, dccLocation, dccLogoutButton,
    dccMarkdown, dccRadioItems, dccRangeSlider, dccSlider, dccStore, dccTab, dccTabs, dccTextarea, dccUpload
library(ggplot2)
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(purrr)
 
# drop down list
drop_list <- list(
    "TV-G",
    "TV-14",
    "TV-MA",
    "TV-PG",
    "R",
    "TV-Y7",
    "TV-Y",
    "PG",
    "G",
    "PG-13",
    "NR",
    "UR",
    "TV-Y7-FV",
    "NC-17")

data = read.csv(file = "data/processed/clean_df.csv")


app <- Dash$new(external_stylesheets = dbcThemes$BOOTSTRAP)

app$layout(
  dbcContainer(
    list(
      dccGraph(id='plot_line'),
      dccDropdown(
        id='rating-select',
        options = drop_list %>%  purrr::map(function(rating,pop) list(label = rating, value = rating)) , 
        value=list("TV-G","TV-MA", "TV-14","TV-Y7"),
        multi=TRUE),
      dccRangeSlider(
        id='my-range-slider',
        min=1942,
        max=2020,
        marks = list(
          '1942' = '1942',
          '1960' = '1960',
          '1980' = '1980',
          '2000' = '2000',
          '2020' = '2020'
          
        ),
        value=list(2003, 2020)
      )
    )
  )
)

app$callback(
  output('plot_line', 'figure'),
  list(input('rating-select', 'value'),
       input('my-range-slider','value')),
  function(ratings_range,year_range) {
    df <- na.omit(data) %>% 
      filter(release_year > year_range[1],release_year < year_range[2]) %>%
      filter(rating %in% ratings_range) %>%
      group_by(release_year,rating) %>% 
      summarise(count = length(rating))
    
    plot  <- ggplot(df ,aes(x = release_year, y = count, color = rating)) +
      geom_line()+      
      scale_size(range = c(2, 12)) +
      ggtitle('Movie rating in Netflix in different years') +
      labs(x = 'Years', y= "Number of movie") +
      theme_bw() +
      theme(text =  element_text(size = 10)) +
      ggthemes::scale_color_tableau() 
    
    ggplotly(plot)
  }
)

app$run_server(debug = T) # use when running locally
⚠ No source directory information available; hot reloading has been disabled.
Please ensure that you are loading your Dash for R application using source().

⚠ Note: As of version 1.0, the following packages are deprecated and should no longer be installed or loaded
when using Dash for R: `dashHtmlComponents`, `dashCoreComponents`, `dashTable`. These components are now
bundled within the `dash` package.
Fire started at 127.0.0.1:8050
start: 127.0.0.1:8050
NA
stop: 127.0.0.1:8050

drop_list <- list("TV-G",
                  "TV-14",
                  "TV-MA"
                  )
options <- drop_list %>%  purrr::map(function(rating,pop) list(label = rating, value = rating))

options
[[1]]
[[1]]$label
[1] "TV-G"

[[1]]$value
[1] "TV-G"


[[2]]
[[2]]$label
[1] "TV-14"

[[2]]$value
[1] "TV-14"


[[3]]
[[3]]$label
[1] "TV-MA"

[[3]]$value
[1] "TV-MA"
# testing <- data |>
#   select(rating, title) |>
#   group_by(rating) 
# 
# 
# str(data$rating)
# drop_list <- list("TV-G",
#                   "TV-14",
#                   "TV-MA"
#                   )
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CiMgYmFzZSB3b3JraW5nCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkcikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRhc2hIdG1sQ29tcG9uZW50cykKbGlicmFyeShkYXNoQ29yZUNvbXBvbmVudHMpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGRhc2gpCmxpYnJhcnkocHVycnIpCgpzdWZfZGF0YSA8LSByZWFkLmNzdihmaWxlID0gJ2RhdGEvcHJvY2Vzc2VkL3N1ZmFuZ19jbGVhbl9kZi5jc3YnKQpqX2RhdGEgPC0gcmVhZF9jc3YoImRhdGEvcHJvY2Vzc2VkL2phc21pbmVfZGYuY3N2IikKZGF0YSA8LSByZWFkX2NzdigiZGF0YS9wcm9jZXNzZWQvY2xlYW5fZGYuY3N2IikKCmpfZGF0YSA8LSBqX2RhdGEgJT4lIGZpbHRlcihpcy5uYShqX2RhdGEkY2FzdF9jb3VudCkgPT0gRkFMU0UpCgpjYXN0X2RhdGEgPC0gal9kYXRhICU+JSAKICBncm91cF9ieShyZWxlYXNlX3llYXIpICU+JQogIHN1bW1hcml6ZShtZWFuX2Nhc3RfY291bnQgPSBtZWFuKGNhc3RfY291bnQpKQpgYGAKCmBgYHtyfQogcCA8LSBjYXN0X2RhdGEgJT4lCiAgICAgIGdncGxvdChhZXMoeD1yZWxlYXNlX3llYXIsCiAgICAgICAgICAgICAgICAgeT1tZWFuX2Nhc3RfY291bnQpKSArCiAgICAgIGdlb21fcG9pbnQoZmlsbD0gInJlZDIiLCBjb2xvciA9ICJibGFjayIsIHNoYXBlID0gMjEsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkF2ZXJhZ2UgQ2FzdCBTaXplIFBlciBZZWFyIikgKwogICAgICB4bGFiKCJSZWxlYXNlIFllYXIiKSArCiAgICAgIHlsYWIoIkF2Zy4gQ2FzdCBTaXplIikgKwogICAgICB4bGltKDE5NDIsIDIwMjApICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgY29sb3IgPSAid2hpdGUiKSwKICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTAiKSwKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpLAogICAgICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICcjMTcxNjE0JywgY29sb3VyID0gJyMxNzE2MTQnKSwKICAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJ3aGl0ZSIpLAogICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiksCiAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiKQogICAgICApCiAgICBnZ3Bsb3RseShwICsgYWVzKHRleHQgPSByZWxlYXNlX3llYXIpLCB0b29sdGlwID0gJ3JlbGVhc2VfeWVhcicpICAlPiUgbGF5b3V0KHBsb3RfYmdjb2xvciA9ICcwMDAwMDAnKQpgYGAKYGBge3J9CmMoIiNDRTI2MjYiLCAKICAiIzgyMDI2MyIsIAogICIjRkJCQTcyIiwgCiAgIiNFRkFBQzQiLCAKICAiI0E1NjEyNCIsIAogICIjRDMwQzdCIiwKICAiIzUyMEYyQSIsIAogICIjRkYzQzM4IiwgCiAgIiNGRjhDNDIiLCAKICAiI0Y5OTFDQyIsIAogICIjQTA1QkZBIiwgCiAgIiM5RjIwNDIiKQpgYGAKCmBgYHtyfQpzdW1tYXJpemUobWVhbl9jYXN0X2NvdW50ID0gbWVhbihjYXN0X2NvdW50KSkKCmFwcCA8LSBEYXNoJG5ldyhleHRlcm5hbF9zdHlsZXNoZWV0cyA9IGRiY1RoZW1lcyRCT09UU1RSQVApCgoKYXBwJGxheW91dCgKICBkYmNDb250YWluZXIoCiAgICBsaXN0KAogICAgCiAgICAjIHRpdGxlIGNhcmQgCiAgICBkYmNSb3coCiAgICAgIGxpc3QoCiAgICAgICAgZGJjQ2FyZCgKICAgICAgICAgIGRiY0NhcmRCb2R5KAogICAgICAgICAgICBsaXN0KGg0KCJOZXRmbGl4IE1vdmllIERhc2hib2FyZDogVmlzdWFsaXplIG1vdmllIHRyZW5kcyBvbiB0aGUgd29ybGQncyBtb3N0IHBvcHVsYXIgc3RyZWFtaW5nIHBsYXRmb3JtISIsIGNsYXNzTmFtZSA9ICJjYXJkLXRpdGxlIikpLAogICAgICAgICAgICBkYmNDb2woCiAgICAgICAgICAgIHN0eWxlPWxpc3QoImZvbnQtd2VpZ2h0Ij0iYm9sZCIsICJmb250LXNpemUiPSI4NSUiKSwKICAgICAgICAgICAgKSwgIyBkYmNDb2wKICAgICAgICAgICksICMgZGJjQ2FyZEJvZHkKICAgICAgICAgIGNvbG9yID0iZGFyayIsIAogICAgICAgICAgaW52ZXJzZT1UUlVFCiAgICAgICAgKSAjZGJjQ2FyZAogICAgKSwgIyBsaXN0CiAgICApLCAjIGRiY1JvdwogICAgCiAgICAjIGZpcnN0IHJvdwogICAgIGRiY1JvdygKICAgICAgbGlzdCgKICAgICAgCiAgICAgICAjIEphc21pbmUncyBwbG90CiAgICAgICAgIGRiY0NvbCggCiAgICAgICAgICBkYmNDYXJkKAogICAgICAgICAgICBkYmNDYXJkQm9keSgKICAgICAgICAgICAgICBkaXYoCiAgICAgICAgICAgICAgICAgbGlzdCgKICAgICAgICAgICAgICAgICAgZGNjR3JhcGgoaWQ9J3NjYXR0ZXInKSwKICAgICAgICAgICAgICAgICAgaHRtbExhYmVsKCdZZWFyIFJhbmdlJyksCiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBkY2NTbGlkZXIoCiAgICAgICAgICAgICAgICAgICAgaWQ9J3hzbGlkZXInLAogICAgICAgICAgICAgICAgICAgIG1pbj0xOTQyLAogICAgICAgICAgICAgICAgICAgIG1heD0yMDE5LAogICAgICAgICAgICAgICAgICAgIG1hcmtzID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICAgICcxOTQyJyA9ICcxOTQyJywKICAgICAgICAgICAgICAgICAgICAgICcxOTYyJyA9ICcxOTYyJywKICAgICAgICAgICAgICAgICAgICAgICcxOTgyJyA9ICcxOTgyJywKICAgICAgICAgICAgICAgICAgICAgICcyMDAyJyA9ICcyMDAyJywKICAgICAgICAgICAgICAgICAgICAgICcyMDE5Jz0gJzIwMTknCiAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICB2YWx1ZT0yMDAyKQogICAgICAgICAgICAgICkKICAgICAgICAgICAgICAKICAgICAgICAgICAgKSAjIGh0bWwKICAgICAgICAgICksICMgZGJjQ2FyZEJvZHkKICAgICAgICBjb2xvcj0iZGFyayIKICAgICAgICApLCAjIGRiY0NhcmQKICAgICAgICBtZD02LAogICAgICApLCAjIEphc21pbmUgZGJjQ29sCiAgICAgIAogICAgICAjIE1haHNhIHBsb3QKICAgICAgCiAgICAgIGRiY0NvbCgKICAgICAgICAgIGRiY0NhcmQoCiAgICAgICAgICAgIGRiY0NhcmRCb2R5KAogICAgICAgICAgICAgIGRpdigKICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgIGRjY0dyYXBoKGlkPSdwbG90X2xpbmUnKSwKCiAgICAgICAgICAgICAgICAgIGRjY0Ryb3Bkb3duKAogICAgICAgICAgICAgICAgICAgIGlkPSdyYXRpbmctc2VsZWN0JywKICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gZGF0YSRyYXRpbmcgJT4lCiAgICAgICAgICAgICAgICAgICAgICBwdXJycjo6bWFwKGZ1bmN0aW9uKHJhdGluZyxwb3ApIGxpc3QobGFiZWwgPSByYXRpbmcsIHZhbHVlID0gcmF0aW5nKSksCiAgICAgICAgICAgICAgICAgICAgdmFsdWU9bGlzdCgiVFYtRyIsIlRWLU1BIiwgIlRWLTE0IiwiVFYtWTciKSwKICAgICAgICAgICAgICAgICAgICBtdWx0aT1UUlVFCiAgICAgICAgICAgICAgICAgICAgKSwKCiAgICAgICAgICAgICAgICAgIGRjY1JhbmdlU2xpZGVyKAogICAgICAgICAgICAgICAgICAgIGlkPSdteS1yYW5nZS1zbGlkZXInLAogICAgICAgICAgICAgICAgICAgIG1pbj0xOTQyLAogICAgICAgICAgICAgICAgICAgIG1heD0yMDIwLAogICAgICAgICAgICAgICAgICAgIG1hcmtzID0KICAgICAgICAgICAgICAgICAgICAgIGxpc3QoCiAgICAgICAgICAgICAgICAgICAgICAgICcxOTQyJyA9ICcxOTQyJywKICAgICAgICAgICAgICAgICAgICAgICAgJzE5NjAnID0gJzE5NjAnLAogICAgICAgICAgICAgICAgICAgICAgICAnMTk4MCcgPSAnMTk4MCcsCiAgICAgICAgICAgICAgICAgICAgICAgICcyMDAwJyA9ICcyMDAwJywKICAgICAgICAgICAgICAgICAgICAgICAgJzIwMjAnID0gJzIwMjAnCiAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgIHZhbHVlPWxpc3QoMjAwMywgMjAyMCkKICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKSAjIGxpc3QKICAgICAgICAgICAgICApICMgZGl2CiAgICAgICAgICAgICksICMgZGJjQ2FyZEJvZHkKICAgICAgICAgICAgY29sb3I9ImRhcmsiCiAgICAgICAgICApLCAjIGRiY0NhcmQKICAgIG1kPTYpLCAjIGNsb3NlIGRiY0NvbAogICAgICAKICAgIGRiY1JvdygKICAgICAgZGJjQ29sKAogICAgICAgIGRiY0NhcmQoCiAgICAgICAgIGRiY0NhcmRCb2R5KAogICAgICAgICAgICAgIGRpdigKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgIyMKICAgICAgICAgICAgICAgIAogICAgICBsaXN0KAogICAgICBkY2NHcmFwaChpZD0ncGxvdC1hcmVhJyksCiAgICAgIGh0bWxMYWJlbCgiWWVhciIpLAogICAgICBkY2NSYW5nZVNsaWRlcihpZD0neWVhcjMnLAogICAgICAgICAgICAgICAgbWluID0gbWluKHN1Zl9kYXRhJHJlbGVhc2VfeWVhciksCiAgICAgICAgICAgICAgICBtYXg9IG1heChzdWZfZGF0YSRyZWxlYXNlX3llYXIpLAogICAgICAgICAgICAgICAgdmFsdWU9bGlzdCgxOTk1LCAyMDIwKSwKICAgICAgICAgICAgICAgIG1hcmtzPWxpc3QoCiAgICAgICAgICAgICAgICAgICcxOTcwJz0gIjE5NzAiLAogICAgICAgICAgICAgICAgICAnMTk3NSc9ICIxOTc1IiwKICAgICAgICAgICAgICAgICAgJzE5ODAnPSAiMTk4MCIsCiAgICAgICAgICAgICAgICAgICcxOTg1Jz0gIjE5ODUiLAogICAgICAgICAgICAgICAgICAnMTk5MCc9ICIxOTkwIiwKICAgICAgICAgICAgICAgICAgJzE5OTUnPSAiMTk5NSIsCiAgICAgICAgICAgICAgICAgICcyMDAwJz0gIjIwMDAiLAogICAgICAgICAgICAgICAgICAnMjAwNSc9ICIyMDA1IiwKICAgICAgICAgICAgICAgICAgJzIwMTAnPSAiMjAxMCIsCiAgICAgICAgICAgICAgICAgICcyMDE1Jz0gIjIwMTUiLAogICAgICAgICAgICAgICAgICAnMjAyMCc9ICIyMDIwIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKSwKICAgICAgaHRtbExhYmVsKCJEdXJhdGlvbiIpLAogICAgICBkY2NSYW5nZVNsaWRlcihpZD0nZHVyYXRpb24zJywKICAgICAgICAgICAgICAgIG1pbiA9IG1pbihzdWZfZGF0YSRkdXJhdGlvbiksCiAgICAgICAgICAgICAgICBtYXggPSBtYXgoc3VmX2RhdGEkZHVyYXRpb24pLAogICAgICAgICAgICAgICAgdmFsdWU9bGlzdCg2MCwgMTIwKSwKICAgICAgICAgICAgICAgIG1hcmtzPWxpc3QoCiAgICAgICAgICAgICAgICAgICcxMCc9ICAiMTAgbWluIiwKICAgICAgICAgICAgICAgICAgJzMwJz0gIjMwIG1pbiIsCiAgICAgICAgICAgICAgICAgICc1MCc9ICI1MCBtaW4iLAogICAgICAgICAgICAgICAgICAnNzAnPSAiNzAgbWluIiwKICAgICAgICAgICAgICAgICAgJzkwJz0gIjkwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcxMTAnPSAiMTEwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcxMzAnPSAiMTMwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcxNTAnPSAiMTUwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcxNzAnPSAiMTcwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcxOTAnPSAiMTkwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcyMTAnPSAiMjEwIG1pbiIsCiAgICAgICAgICAgICAgICAgICcyMzAnPSAiMjMwIG1pbiIpCiAgICAgICAgICApCiAgICAgICAgKQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAjIyMKICAgICAgICAgICAgICApICMgZGl2CiAgICAgICAgICksICMgZGJjQ2FyZEJvZHkKICAgICAgY29sb3I9ImRhcmsiCiAgICAgICAgKSAjIGRiY0NhcmQKICAgICAgKQogICAgKQoKICAgICAgKSAjIGNsb3NlIGxpc3QKICAgICkgIyBmaXJzdCByb3cKICAgICksICMgY2xvc2UgbGlzdAogICAgc3R5bGU9bGlzdChiYWNrZ3JvdW5kQ29sb3IgPSAiIzAwMDAwMCIpCiAgKSAjIGNvbnRhaW5lciAgCikgCgojIGphc21pbmUgY2FsbGJhY2sgCmFwcCRjYWxsYmFjaygKICBvdXRwdXQoJ3NjYXR0ZXInLCAnZmlndXJlJyksCiAgbGlzdChpbnB1dCgneHNsaWRlcicsICd2YWx1ZScpKSwKICBmdW5jdGlvbih4Y29sKSB7CgogICAgcCA8LSBjYXN0X2RhdGEgJT4lCiAgICAgIGdncGxvdChhZXMoeD1yZWxlYXNlX3llYXIsCiAgICAgICAgICAgICAgICAgeT1tZWFuX2Nhc3RfY291bnQpKSArCiAgICAgIGdlb21fcG9pbnQoZmlsbD0gInJlZDIiLCBjb2xvciA9ICJibGFjayIsIHNoYXBlID0gMjEsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkF2ZXJhZ2UgQ2FzdCBTaXplIFBlciBZZWFyIikgKwogICAgICB4bGFiKCJSZWxlYXNlIFllYXIiKSArCiAgICAgIHlsYWIoIkF2Zy4gQ2FzdCBTaXplIikgKwogICAgICB4bGltKDE5NDIsIHhjb2wpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiksCiAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAnIzE3MTYxNCcsIGNvbG91ciA9ICcjMTcxNjE0JykKICAgICAgICAgICAgCiAgICAgICkKICAgIGdncGxvdGx5KHAgKyBhZXModGV4dCA9IHJlbGVhc2VfeWVhciksIHRvb2x0aXAgPSAncmVsZWFzZV95ZWFyJykgICU+JSBsYXlvdXQocGxvdF9iZ2NvbG9yID0gJzAwMDAwMCcpCiAgfQopCgojIG1haHNhCgphcHAkY2FsbGJhY2soCiAgb3V0cHV0KCdwbG90X2xpbmUnLCAnZmlndXJlJyksCiAgbGlzdChpbnB1dCgncmF0aW5nLXNlbGVjdCcsICd2YWx1ZScpLAogICAgICAgaW5wdXQoJ215LXJhbmdlLXNsaWRlcicsJ3ZhbHVlJykpLAogIGZ1bmN0aW9uKHJhdGluZ3NfcmFuZ2UseWVhcl9yYW5nZSkgewogICAgZGYgPC0gbmEub21pdChkYXRhKSAlPiUgCiAgICAgIGZpbHRlcihyZWxlYXNlX3llYXIgPiB5ZWFyX3JhbmdlWzFdLHJlbGVhc2VfeWVhciA8IHllYXJfcmFuZ2VbMl0pICU+JQogICAgICBmaWx0ZXIocmF0aW5nICVpbiUgcmF0aW5nc19yYW5nZSkgJT4lCiAgICAgIGdyb3VwX2J5KHJlbGVhc2VfeWVhcixyYXRpbmcpICU+JSAKICAgICAgc3VtbWFyaXNlKGNvdW50ID0gbGVuZ3RoKHJhdGluZykpCiAgICAKICAgIHBsb3QgIDwtIGdncGxvdChkZiAsYWVzKHggPSByZWxlYXNlX3llYXIsIHkgPSBjb3VudCwgY29sb3IgPSByYXRpbmcpKSArCiAgICAgIGdlb21fbGluZSgpKyAgICAgIAogICAgICBzY2FsZV9zaXplKHJhbmdlID0gYygyLCAxMikpICsKICAgICAgZ2d0aXRsZSgnTW92aWUgcmF0aW5nIGluIE5ldGZsaXggaW4gZGlmZmVyZW50IHllYXJzJykgKwogICAgICBsYWJzKHggPSAnWWVhcnMnLCB5PSAiTnVtYmVyIG9mIG1vdmllIikgKwogICAgICB0aGVtZV9idygpICsKICAgICAgdGhlbWUodGV4dCA9ICBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKwogICAgICBnZ3RoZW1lczo6c2NhbGVfY29sb3JfdGFibGVhdSgpIAogICAgCiAgICBnZ3Bsb3RseShwbG90KQogIH0KKQoKIyBzdWZhbmcgY2FsbGJhY2sKCmFwcCRjYWxsYmFjaygKICBvdXRwdXQoJ3Bsb3QtYXJlYScsICdmaWd1cmUnKSwKICBsaXN0KGlucHV0KCd5ZWFyMycsICd2YWx1ZScpLAogICAgICAgaW5wdXQoJ2R1cmF0aW9uMycsICd2YWx1ZScpKSwKICBmdW5jdGlvbih5ZWFyX3JhbmdlLGR1cmF0aW9uX3JhbmdlKXsKICAgIGRhdGFfZmlsdCA8LSBzdWZfZGF0YSAlPiUKICAgICAgZHBseXI6OmZpbHRlcigocmVsZWFzZV95ZWFyID4geWVhcl9yYW5nZVsxXSAmIHJlbGVhc2VfeWVhciA8IHllYXJfcmFuZ2VbMl0pICYgKGR1cmF0aW9uID4gZHVyYXRpb25fcmFuZ2VbMV0gJiBkdXJhdGlvbiA8IGR1cmF0aW9uX3JhbmdlWzJdKSkKICAgIHAxIDwtIGdncGxvdChkYXRhX2ZpbHQsIGFlcyh4ID0gZm9yY2F0czo6ZmN0X2luZnJlcShjb3VudHJ5KSksdGV4dCA9IG5hbWUpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICdjb3VudCcsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJyZWQyIikgKwogICAgICBnZ3RpdGxlKCdXaGljaCBDb3VudHJpZXMgTWFrZSB0aGUgTW9zdCBNb3ZpZXM/JykgKwogICAgICBsYWJzKHggPSAnQ291bnRyeScpICsKICAgICAgbGFicyh5ID0gJ051bWJlciBvZiBNb3ZpZXMgUHJvZHVjZWQnKSsKICAgICAgdGhlbWVfY2xhc3NpYygpICsKICAgICAgZ2d0aGVtZXM6OnNjYWxlX2NvbG9yX3RhYmxlYXUoKSsKICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQogICAgZ2dwbG90bHkocDEpCiAgfQopCgoKIyBhcHAkcnVuX3NlcnZlcihob3N0ID0gJzAuMC4wLjAnKQphcHAkcnVuX3NlcnZlcihkZWJ1ZyA9IFQpICMgdXNlIHdoZW4gcnVubmluZyBsb2NhbGx5CmBgYAoKCmBgYHtyfQoKIyB3b3JrIG9uIApsaWJyYXJ5KGRhc2gpCmxpYnJhcnkoZGFzaENvcmVDb21wb25lbnRzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KHB1cnJyKQogCiMgZHJvcCBkb3duIGxpc3QKZHJvcF9saXN0IDwtIGxpc3QoCiAgICAiVFYtRyIsCiAgICAiVFYtMTQiLAogICAgIlRWLU1BIiwKICAgICJUVi1QRyIsCiAgICAiUiIsCiAgICAiVFYtWTciLAogICAgIlRWLVkiLAogICAgIlBHIiwKICAgICJHIiwKICAgICJQRy0xMyIsCiAgICAiTlIiLAogICAgIlVSIiwKICAgICJUVi1ZNy1GViIsCiAgICAiTkMtMTciKQoKZGF0YSA9IHJlYWQuY3N2KGZpbGUgPSAiZGF0YS9wcm9jZXNzZWQvY2xlYW5fZGYuY3N2IikKCgphcHAgPC0gRGFzaCRuZXcoZXh0ZXJuYWxfc3R5bGVzaGVldHMgPSBkYmNUaGVtZXMkQk9PVFNUUkFQKQoKYXBwJGxheW91dCgKICBkYmNDb250YWluZXIoCiAgICBsaXN0KAogICAgICBkY2NHcmFwaChpZD0ncGxvdF9saW5lJyksCiAgICAgIGRjY0Ryb3Bkb3duKAogICAgICAgIGlkPSdyYXRpbmctc2VsZWN0JywKICAgICAgICBvcHRpb25zID0gZHJvcF9saXN0ICU+JSAgcHVycnI6Om1hcChmdW5jdGlvbihyYXRpbmcscG9wKSBsaXN0KGxhYmVsID0gcmF0aW5nLCB2YWx1ZSA9IHJhdGluZykpICwgCiAgICAgICAgdmFsdWU9bGlzdCgiVFYtRyIsIlRWLU1BIiwgIlRWLTE0IiwiVFYtWTciKSwKICAgICAgICBtdWx0aT1UUlVFKSwKICAgICAgZGNjUmFuZ2VTbGlkZXIoCiAgICAgICAgaWQ9J215LXJhbmdlLXNsaWRlcicsCiAgICAgICAgbWluPTE5NDIsCiAgICAgICAgbWF4PTIwMjAsCiAgICAgICAgbWFya3MgPSBsaXN0KAogICAgICAgICAgJzE5NDInID0gJzE5NDInLAogICAgICAgICAgJzE5NjAnID0gJzE5NjAnLAogICAgICAgICAgJzE5ODAnID0gJzE5ODAnLAogICAgICAgICAgJzIwMDAnID0gJzIwMDAnLAogICAgICAgICAgJzIwMjAnID0gJzIwMjAnCiAgICAgICAgICAKICAgICAgICApLAogICAgICAgIHZhbHVlPWxpc3QoMjAwMywgMjAyMCkKICAgICAgKQogICAgKQogICkKKQoKYXBwJGNhbGxiYWNrKAogIG91dHB1dCgncGxvdF9saW5lJywgJ2ZpZ3VyZScpLAogIGxpc3QoaW5wdXQoJ3JhdGluZy1zZWxlY3QnLCAndmFsdWUnKSwKICAgICAgIGlucHV0KCdteS1yYW5nZS1zbGlkZXInLCd2YWx1ZScpKSwKICBmdW5jdGlvbihyYXRpbmdzX3JhbmdlLHllYXJfcmFuZ2UpIHsKICAgIGRmIDwtIG5hLm9taXQoZGF0YSkgJT4lIAogICAgICBmaWx0ZXIocmVsZWFzZV95ZWFyID4geWVhcl9yYW5nZVsxXSxyZWxlYXNlX3llYXIgPCB5ZWFyX3JhbmdlWzJdKSAlPiUKICAgICAgZmlsdGVyKHJhdGluZyAlaW4lIHJhdGluZ3NfcmFuZ2UpICU+JQogICAgICBncm91cF9ieShyZWxlYXNlX3llYXIscmF0aW5nKSAlPiUgCiAgICAgIHN1bW1hcmlzZShjb3VudCA9IGxlbmd0aChyYXRpbmcpKQogICAgCiAgICBwbG90ICA8LSBnZ3Bsb3QoZGYgLGFlcyh4ID0gcmVsZWFzZV95ZWFyLCB5ID0gY291bnQsIGNvbG9yID0gcmF0aW5nKSkgKwogICAgICBnZW9tX2xpbmUoKSsgICAgICAKICAgICAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMiwgMTIpKSArCiAgICAgIGdndGl0bGUoJ01vdmllIHJhdGluZyBpbiBOZXRmbGl4IGluIGRpZmZlcmVudCB5ZWFycycpICsKICAgICAgbGFicyh4ID0gJ1llYXJzJywgeT0gIk51bWJlciBvZiBtb3ZpZSIpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIHRoZW1lKHRleHQgPSAgZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICAgICAgZ2d0aGVtZXM6OnNjYWxlX2NvbG9yX3RhYmxlYXUoKSAKICAgIAogICAgZ2dwbG90bHkocGxvdCkKICB9CikKCmFwcCRydW5fc2VydmVyKGRlYnVnID0gVCkgIyB1c2Ugd2hlbiBydW5uaW5nIGxvY2FsbHkKCmBgYAoKYGBge3J9Cgpkcm9wX2xpc3QgPC0gbGlzdCgKICAgICJUVi1HIiwKICAgICJUVi0xNCIsCiAgICAiVFYtTUEiLAogICAgIlRWLVBHIiwKICAgICJSIiwKICAgICJUVi1ZNyIsCiAgICAiVFYtWSIsCiAgICAiUEciLAogICAgIkciLAogICAgIlBHLTEzIiwKICAgICJOUiIsCiAgICAiVVIiLAogICAgIlRWLVk3LUZWIiwKICAgICJOQy0xNyIpCgpvcHRpb25zIDwtIGRyb3BfbGlzdCAlPiUgIHB1cnJyOjptYXAoZnVuY3Rpb24ocmF0aW5nLHBvcCkgbGlzdChsYWJlbCA9IHJhdGluZywgdmFsdWUgPSByYXRpbmcpKQoKb3B0aW9ucwojIHRlc3RpbmcgPC0gZGF0YSB8PgojICAgc2VsZWN0KHJhdGluZywgdGl0bGUpIHw+CiMgICBncm91cF9ieShyYXRpbmcpIAojIAojIAojIHN0cihkYXRhJHJhdGluZykKIyBkcm9wX2xpc3QgPC0gbGlzdCgiVFYtRyIsCiMgICAgICAgICAgICAgICAgICAgIlRWLTE0IiwKIyAgICAgICAgICAgICAgICAgICAiVFYtTUEiCiMgICAgICAgICAgICAgICAgICAgKQpgYGAKCg==